home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / nt / emacssrc.zip / EMACSSRC.TAR / emacs-19.17 / src / ntinevt.c < prev    next >
C/C++ Source or Header  |  1993-11-22  |  14KB  |  482 lines

  1. /*
  2.    Input event support for Windows NT(tm) port of GNU Emacs.
  3.    Copyright (C) 1992 Free Software Foundation, Inc.
  4.  
  5.    This file is part of GNU Emacs.
  6.  
  7.    GNU Emacs is free software; you can redistribute it and/or modify it
  8.    under the terms of the GNU General Public License as published by the
  9.    Free Software Foundation; either version 1, or (at your option) any later
  10.    version.
  11.  
  12.    GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
  13.    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14.    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  15.    more details.
  16.  
  17.    You should have received a copy of the GNU General Public License along
  18.    with GNU Emacs; see the file COPYING.  If not, write to the Free Software
  19.    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.    Drew Bliss                   01-Oct-93
  22.      Adapted from ntkbd.c by Tim Fleehart
  23. */
  24.  
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27.  
  28. #include "config.h"
  29.  
  30. #include <windows.h>
  31.  
  32. #include "lisp.h"
  33. #include "frame.h"
  34. #include "blockinput.h"
  35. #include "termhooks.h"
  36. #include "dispnew_d.h"
  37.  
  38. #include "ntinevt_p.h"
  39.  
  40. /* stdout and standard attributes, from ntterm */
  41. extern HANDLE CurScreen;
  42. extern UCHAR CAttr;
  43.  
  44. /* stdin, from ntterm */
  45. extern HANDLE Keyboard;
  46.  
  47. /* Indicate mouse motion, from keyboard.c */
  48. extern int mouse_moved;
  49.  
  50. /* Info for last mouse motion */
  51. static COORD movement_pos;
  52. static DWORD movement_time;
  53.  
  54. /* Event queue */
  55. #define EVENT_QUEUE_SIZE 50
  56. static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
  57. static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
  58.  
  59. static int FillQueue(BOOL block)
  60. {
  61.     BOOL rc;
  62.     DWORD events_waiting;
  63.  
  64.     if (queue_ptr < queue_end)
  65.         return queue_end-queue_ptr;
  66.     
  67.     if (!block)
  68.     {
  69.         /* Check to see if there are some events to read before we try
  70.            because we can't block */
  71.         if (!GetNumberOfConsoleInputEvents(Keyboard, &events_waiting))
  72.             return -1;
  73.         if (events_waiting == 0)
  74.             return 0;
  75.     }
  76.  
  77.     rc = ReadConsoleInput(Keyboard, event_queue, EVENT_QUEUE_SIZE,
  78.                           &events_waiting);
  79.     if (!rc)
  80.         return -1;
  81.     queue_ptr = event_queue;
  82.     queue_end = event_queue+events_waiting;
  83.     return (int)events_waiting;
  84. }
  85.  
  86. /*
  87.   In a generic, multi-frame world this should take a console handle
  88.   and return the frame for it
  89.  
  90.   Right now, there's only one frame so return it
  91.   */
  92. static FRAME_PTR Win32Frame(void)
  93. {
  94.     return selected_frame;
  95. }
  96.  
  97. #ifdef MULTI_FRAME
  98. #define SET_FRAME(o, f) XSET(o, Lisp_Frame, f)
  99. #else
  100. #define SET_FRAME(o, f) ((o) = Qnil)
  101. #endif
  102.  
  103. /*
  104.   Translate console modifiers to emacs modifiers
  105.   */
  106. static int Win32ModToEmacs(DWORD mods)
  107. {
  108.     return ((mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) ?
  109.             meta_modifier : 0) |
  110.                 ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) ?
  111.                  ctrl_modifier : 0) |
  112.                      ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) ?
  113.                       shift_modifier : 0);
  114.             
  115. }
  116.  
  117. /*
  118.   Map virtual key codes into:
  119.   -1 - Ignore this key
  120.   -2 - ASCII char
  121.   Other - Map non-ASCII keys into X keysyms so that they are looked up
  122.   correctly in keyboard.c
  123.   */
  124. /*
  125.   Return, escape and tab are mapped to ASCII rather than coming back
  126.   as non-ASCII to be more compatible with old-style keyboard support
  127.   */
  128. static int map_virt_key[256] =
  129. {
  130.     -1,
  131.     -1,                 /* VK_LBUTTON */
  132.     -1,                 /* VK_RBUTTON */
  133.     0x69,               /* VK_CANCEL */
  134.     -1,                 /* VK_MBUTTON */
  135.     -1, -1, -1,
  136.     8,                  /* VK_BACK */
  137.     -2,                 /* VK_TAB */
  138.     -1, -1,
  139.     11,                 /* VK_CLEAR */
  140.     -2,                 /* VK_RETURN */
  141.     -1, -1,
  142.     -1,                 /* VK_SHIFT */
  143.     -1,                 /* VK_CONTROL */
  144.     -1,                 /* VK_MENU */
  145.     0x13,               /* VK_PAUSE */
  146.     -1,                 /* VK_CAPITAL */
  147.     -1, -1, -1, -1, -1, -1,
  148.     -2,                 /* VK_ESCAPE */
  149.     -1, -1, -1, -1,
  150.     -2,                 /* VK_SPACE */
  151.     0x55,               /* VK_PRIOR */
  152.     0x56,               /* VK_NEXT */
  153.     0x57,               /* VK_END */
  154.     0x50,               /* VK_HOME */
  155.     0x51,               /* VK_LEFT */
  156.     0x52,               /* VK_UP */
  157.     0x53,               /* VK_RIGHT */
  158.     0x54,               /* VK_DOWN */
  159.     0x60,               /* VK_SELECT */
  160.     0x61,               /* VK_PRINT */
  161.     0x62,               /* VK_EXECUTE */
  162.     -1,                 /* VK_SNAPSHOT */
  163.     0x63,               /* VK_INSERT */
  164.     0xff,               /* VK_DELETE */
  165.     0x6a,               /* VK_HELP */
  166.     -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,     /* 0 - 9 */
  167.     -1, -1, -1, -1, -1, -1, -1,
  168.     -2, -2, -2, -2, -2, -2, -2, -2,             /* A - Z */
  169.     -2, -2, -2, -2, -2, -2, -2, -2,
  170.     -2, -2, -2, -2, -2, -2, -2, -2,
  171.     -2, -2,
  172.     -1, -1, -1, -1, -1,
  173.     0xb0,               /* VK_NUMPAD0 */
  174.     0xb1,               /* VK_NUMPAD1 */
  175.     0xb2,               /* VK_NUMPAD2 */
  176.     0xb3,               /* VK_NUMPAD3 */
  177.     0xb4,               /* VK_NUMPAD4 */
  178.     0xb5,               /* VK_NUMPAD5 */
  179.     0xb6,               /* VK_NUMPAD6 */
  180.     0xb7,               /* VK_NUMPAD7 */
  181.     0xb8,               /* VK_NUMPAD8 */
  182.     0xb9,               /* VK_NUMPAD9 */
  183.     0xaa,               /* VK_MULTIPLY */
  184.     0xab,               /* VK_ADD */
  185.     0xac,               /* VK_SEPARATOR */
  186.     0xad,               /* VK_SUBTRACT */
  187.     0xae,               /* VK_DECIMAL */
  188.     0xaf,               /* VK_DIVIDE */
  189.     0xbe,               /* VK_F1 */
  190.     0xbf,               /* VK_F2 */
  191.     0xc0,               /* VK_F3 */
  192.     0xc1,               /* VK_F4 */
  193.     0xc2,               /* VK_F5 */
  194.     0xc3,               /* VK_F6 */
  195.     0xc4,               /* VK_F7 */
  196.     0xc5,               /* VK_F8 */
  197.     0xc6,               /* VK_F9 */
  198.     0xc7,               /* VK_F10 */
  199.     0xc8,               /* VK_F11 */
  200.     0xc9,               /* VK_F12 */
  201.     0xca,               /* VK_F13 */
  202.     0xcb,               /* VK_F14 */
  203.     0xcc,               /* VK_F15 */
  204.     0xcd,               /* VK_F16 */
  205.     0xce,               /* VK_F17 */
  206.     0xcf,               /* VK_F18 */
  207.     0xd0,               /* VK_F19 */
  208.     0xd1,               /* VK_F20 */
  209.     0xd2,               /* VK_F21 */
  210.     0xd3,               /* VK_F22 */
  211.     0xd4,               /* VK_F23 */
  212.     0xd5,               /* VK_F24 */
  213.     -1, -1, -1, -1, -1, -1, -1, -1,
  214.     0x7f,               /* VK_NUMLOCK */
  215.     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9f */
  216.     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xaf */
  217.     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb9 */
  218.     -2,                 /* ; */
  219.     -2,                 /* = */
  220.     -2,                 /* , */
  221.     -2,                 /* \ */
  222.     -2,                 /* . */
  223.     -2,                 /* / */
  224.     -2,                 /* ` */
  225.     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xcf */
  226.     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xda */
  227.     -2,                 /* [ */
  228.     -2,                 /* - */
  229.     -2,                 /* ] */
  230.     -2,                 /* ' */
  231.     -1, /* 0xdf */
  232.     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xef */
  233.     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xff */
  234. };
  235.  
  236. static int KeyEvent(KEY_EVENT_RECORD *event,
  237.                     struct input_event *emacs_ev)
  238. {
  239.     int map;
  240.  
  241.     /*
  242.       Only return key-down events
  243.       */
  244.     if (event->bKeyDown == FALSE)
  245.         return 0;
  246.  
  247.     if (event->wVirtualKeyCode > 0xff)
  248.     {
  249.         printf("Unknown key code %d\n", event->wVirtualKeyCode);
  250.         return 0;
  251.     }
  252.  
  253.     /*
  254.       BUGBUG - Ignores the repeat count
  255.       It's questionable whether we want to obey the repeat count anyway
  256.       since keys usually aren't repeated unless key events back up in
  257.       the queue.  If they're backing up then we don't generally want
  258.       to honor them later since that leads to significant slop in
  259.       cursor motion when the system is under heavy load
  260.       */
  261.     
  262.     map = map_virt_key[event->wVirtualKeyCode];
  263.     if (map == -1)
  264.     {
  265.         return 0;
  266.     }
  267.     else if (map == -2)
  268.     {
  269.         /* ASCII */
  270.         emacs_ev->kind = ascii_keystroke;
  271.         XSET(emacs_ev->code, Lisp_Int, event->uChar.AsciiChar);
  272.     }
  273.     else
  274.     {
  275.         /* non-ASCII */
  276.         emacs_ev->kind = non_ascii_keystroke;
  277.         XSET(emacs_ev->code, Lisp_Int, map);
  278.     }
  279.     SET_FRAME(emacs_ev->frame_or_window, Win32Frame());
  280.     emacs_ev->modifiers = Win32ModToEmacs(event->dwControlKeyState);
  281.     emacs_ev->timestamp = GetTickCount();
  282.     return 1;
  283. }
  284.  
  285. /*
  286.    Mouse position hook
  287.    */
  288. void Win32MousePosition(FRAME_PTR *f,
  289.                         Lisp_Object *bar_window,
  290.                         enum scroll_bar_part *part,
  291.                         Lisp_Object *x,
  292.                         Lisp_Object *y,
  293.                         unsigned long *time)
  294. {
  295.     BLOCK_INPUT;
  296.     
  297.     *f = Win32Frame();
  298.     *bar_window = Qnil;
  299.     *part = 0;
  300.     mouse_moved = 0;
  301.  
  302.     *x = movement_pos.X;
  303.     *y = movement_pos.Y;
  304.     *time = movement_time;
  305.  
  306.     UNBLOCK_INPUT;
  307. }
  308.  
  309. /*
  310.    Remember mouse motion and notify emacs
  311.    */
  312. static void MouseMovedTo(int x, int y)
  313. {
  314.     /* If we're in the same place, ignore it */
  315.     if (x != movement_pos.X || y != movement_pos.Y)
  316.     {
  317.         mouse_moved = 1;
  318.         movement_pos.X = x;
  319.         movement_pos.Y = y;
  320.         movement_time = GetTickCount();
  321.     }
  322. }
  323.  
  324. /*
  325.   Consoles return button bits in a strange order:
  326.   least significant - Leftmost button
  327.   next - Rightmost button
  328.   next - Leftmost+1
  329.   next - Leftmost+2...
  330.  
  331.   Assume emacs likes three button mice, so
  332.   Left == 0
  333.   Middle == 1
  334.   Right == 2
  335.   Others increase from there
  336.   */
  337. static int emacs_button_translation[NUM_MOUSE_BUTTONS] =
  338. {
  339.     0, 2, 1, 3, 4,
  340. };
  341.  
  342. static int MouseEvent(MOUSE_EVENT_RECORD *event,
  343.                       struct input_event *emacs_ev)
  344. {
  345.     static DWORD button_state = 0;
  346.     DWORD but_change, mask;
  347.     int i;
  348.     
  349.     if (event->dwEventFlags == MOUSE_MOVED)
  350.     {
  351.         /*
  352.            For movement events we just note that the mouse has moved
  353.            so that emacs will generate drag events
  354.            */
  355.         MouseMovedTo(event->dwMousePosition.X, event->dwMousePosition.Y);
  356.         return 0;
  357.     }
  358.  
  359.     /*
  360.       It looks like the console code sends us a mouse event with
  361.       dwButtonState == 0 when a window is activated.  Ignore this case
  362.       */
  363.     if (event->dwButtonState == button_state)
  364.         return 0;
  365.     
  366.     emacs_ev->kind = mouse_click;
  367.  
  368.     /*
  369.       Find out what button has changed state since the last button event
  370.       */
  371.     but_change = button_state ^ event->dwButtonState;
  372.     mask = 1;
  373.     for (i = 0; i < NUM_MOUSE_BUTTONS; i++, mask <<= 1)
  374.         if (but_change & mask)
  375.         {
  376.             XSET(emacs_ev->code, Lisp_Int, emacs_button_translation[i]);
  377.             break;
  378.         }
  379.     /*
  380.       If the changed button is out of emacs' range (highly unlikely)
  381.       ignore this event */
  382.     if (i == NUM_MOUSE_BUTTONS)
  383.         return 0;
  384.     
  385.     button_state = event->dwButtonState;
  386.  
  387.     emacs_ev->timestamp = GetTickCount();
  388.  
  389.     emacs_ev->modifiers = Win32ModToEmacs(event->dwControlKeyState) |
  390.         ((event->dwButtonState & mask) ? down_modifier : up_modifier);
  391.  
  392.     XFASTINT(emacs_ev->x) = event->dwMousePosition.X;
  393.     XFASTINT(emacs_ev->y) = event->dwMousePosition.Y;
  394.  
  395.     SET_FRAME(emacs_ev->frame_or_window, Win32Frame());
  396.     
  397.     return 1;
  398. }
  399.  
  400. static void ResizeEvent(WINDOW_BUFFER_SIZE_RECORD *event)
  401. {
  402.     FRAME_PTR f;
  403.  
  404.     /*
  405.        This doesn't really do much interesting because consoles just
  406.        put up scroll bars when you resize them
  407.        But hey, why not?
  408.        */
  409.     f = Win32Frame();
  410.     change_frame_size(f, event->dwSize.Y, event->dwSize.X, 0, 1);
  411.     SET_FRAME_GARBAGED(f);
  412. }
  413.  
  414. int Win32ReadSocket(int sd, struct input_event *bufp, int numchars,
  415.                     int waitp, int expected)
  416. {
  417.     BOOL no_events = TRUE;
  418.     int nev, ret = 0, add;
  419.  
  420.     if (interrupt_input_blocked)
  421.     {
  422.         interrupt_input_pending = 1;
  423.         return -1;
  424.     }
  425.  
  426.     interrupt_input_pending = 0;
  427.     BLOCK_INPUT;
  428.     
  429.     for (;;)
  430.     {
  431.         nev = FillQueue(waitp != 0);
  432.         if (nev <= 0)
  433.         {
  434.             /*
  435.               If nev == -1, there was some kind of error
  436.               If nev == 0 then waitp must be zero and no events were available
  437.               so return
  438.               */
  439.             UNBLOCK_INPUT;
  440.             return nev;
  441.         }
  442.  
  443.         while (nev > 0 && numchars > 0)
  444.         {
  445.             switch(queue_ptr->EventType)
  446.             {
  447.             case KEY_EVENT:
  448.                 add = KeyEvent(&queue_ptr->Event.KeyEvent, bufp);
  449.                 bufp += add;
  450.                 ret += add;
  451.                 numchars -= add;
  452.                 break;
  453.  
  454.             case MOUSE_EVENT:
  455.                 add = MouseEvent(&queue_ptr->Event.MouseEvent, bufp);
  456.                 bufp += add;
  457.                 ret += add;
  458.                 numchars -= add;
  459.                 break;
  460.  
  461.             case WINDOW_BUFFER_SIZE_EVENT:
  462.                 ResizeEvent(&queue_ptr->Event.WindowBufferSizeEvent);
  463.                 break;
  464.             
  465.             case MENU_EVENT:
  466.             case FOCUS_EVENT:
  467.                 /* Internal event types, ignored */
  468.                 break;
  469.             }
  470.             
  471.             queue_ptr++;
  472.             nev--;
  473.         }
  474.  
  475.         if (ret > 0 || expected == 0)
  476.             break;
  477.     }
  478.         
  479.     UNBLOCK_INPUT;
  480.     return ret;
  481. }
  482.